<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { queryHeatMapApi } from '@/api/consume'
import { merchantTypes, ensureMerchantTypes } from '@/shared/merchantTypes'

const form = ref({
  startTime: '',
  endTime: '',
  merchantType: ''
})

let map = null
let heatmapOverlay = null
const baiduReady = ref(false)
const heatmapReady = ref(false)
let currentData = []
const initMap = () => {
  baiduReady.value = !!window.BMap
  heatmapReady.value = !!(window.BMapLib && window.BMapLib.HeatmapOverlay)
  if (!baiduReady.value) {
    ElMessage.error('百度地图未正确加载，请检查网络或AK')
    return
  }
  map = new window.BMap.Map('heatmapContainer')
  const center = new window.BMap.Point(112.940877, 28.193900)
  map.centerAndZoom(center, 13)
  map.enableScrollWheelZoom(true)
// 平滑缩放与惯性拖拽，提升交互流畅度
if (typeof map.enableContinuousZoom === 'function') {
  map.enableContinuousZoom()
}
if (typeof map.enableInertialDragging === 'function') {
  map.enableInertialDragging()
}
// 在缩放时临时隐藏热力图，避免频繁重绘造成卡顿
map.addEventListener('zoomstart', () => {
  if (heatmapOverlay) heatmapOverlay.hide()
})
map.addEventListener('zoomend', () => {
  if (heatmapOverlay) heatmapOverlay.show()
})
// 点击地图显示最近点位详情
map.addEventListener('click', (e) => {
  showDetailAtClosest(e.point)
})
}

const renderHeatmap = (data = []) => {
  if (!(window.BMap && window.BMapLib && window.BMapLib.HeatmapOverlay)) {
    ElMessage.error('热力图插件未就绪')
    return
  }
  currentData = Array.isArray(data) ? data : []
  // 数据转换为热力图格式
  const points = currentData.map(d => ({
    lng: Number(d.longitude),
    lat: Number(d.latitude),
    count: Number(d.weight || 0)
  }))
  if (!heatmapOverlay) {
    heatmapOverlay = new window.BMapLib.HeatmapOverlay({ radius: 15 })
    map.addOverlay(heatmapOverlay)
  }
  const max = points.length ? Math.max(...points.map(p => p.count)) : 100
  heatmapOverlay.setDataSet({ data: points, max })
  heatmapOverlay.show()
  // 自动调整中心点
  if (points.length) {
    const pts = points.map(p => new window.BMap.Point(p.lng, p.lat))
    const view = map.getViewport(pts)
    map.centerAndZoom(view.center, view.zoom)
  }
}

const showDetailAtClosest = (pt) => {
  if (!currentData || !currentData.length || !map) return
  const clickPoint = new window.BMap.Point(pt.lng, pt.lat)
  let best = null
  let bestDist = Infinity
  for (const d of currentData) {
    const p = new window.BMap.Point(Number(d.longitude), Number(d.latitude))
    const dist = map.getDistance(clickPoint, p) // 米
    if (dist < bestDist) {
      bestDist = dist
      best = d
    }
  }
  const zoom = map.getZoom()
  const threshold = zoom >= 15 ? 120 : zoom >= 13 ? 220 : 350 // 距离阈值（米）
  if (!best || bestDist > threshold) return
  const content = `<div>
    <div>商铺名称：<strong>${best.merchantName || '消费地点'}</strong></div>
    <div>单次消费金额：${best.weight ?? 0}</div>
    ${best.detail ? `<div>${best.detail}</div>` : ''}
  </div>`
  const info = new window.BMap.InfoWindow(content, { width: 260, title: '消费地点详情' })
  const pos = new window.BMap.Point(Number(best.longitude), Number(best.latitude))
  map.openInfoWindow(info, pos)
}

const onSearch = async () => {
  if (!baiduReady.value || !heatmapReady.value) {
    ElMessage.error('热力图插件未就绪，请稍后重试')
    return
  }
  if (!form.value.startTime || !form.value.endTime) {
    ElMessage.error('请选择开始和结束时间')
    return
  }
  try {
    const res = await queryHeatMapApi({
      startTime: form.value.startTime,
      endTime: form.value.endTime,
      merchantType: form.value.merchantType || ''
    })
    if (res && res.code) {
      const list = Array.isArray(res.data) ? res.data : []
      renderHeatmap(list)
    } else {
      ElMessage.error(res?.msg || '热力图数据获取失败')
    }
  } catch (e) {
    ElMessage.error('热力图接口访问异常')
  }
}

onMounted(async () => {
  await ensureMerchantTypes()
    initMap()
})
</script>

<template>
  <div class="container">
    <h1>消费地点热力图</h1><br></br>
    <el-form :inline="true" :model="form" class="search-form" @keyup.enter="onSearch">
      <el-form-item label="开始时间">
        <el-date-picker v-model="form.startTime" type="date" value-format="YYYY-MM-DD" placeholder="选择开始时间" style="width: 160px" />
      </el-form-item>
      <el-form-item label="结束时间">
        <el-date-picker v-model="form.endTime" type="date" value-format="YYYY-MM-DD" placeholder="选择结束时间" style="width: 160px" />
      </el-form-item>
      <el-form-item label="商户类型">
        <el-select v-model="form.merchantType" placeholder="全部类型" clearable style="width: 180px">
          <el-option v-for="mt in merchantTypes" :key="mt" :label="mt" :value="mt" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" :disabled="!baiduReady || !heatmapReady" @click="onSearch">查询</el-button>
      </el-form-item>
    </el-form>
  </div>
  <div class="container">
    <el-card shadow="hover">
      <div id="heatmapContainer" class="map"></div>
    </el-card>
  </div>
</template>

<style scoped>
.container {
  margin-top: 15px;
  margin-bottom: 15px;
}
.search-form :deep(.el-form-item) {
  margin-right: 12px;
}
.map {
  width: 100%;
  height: 520px;
  will-change: transform;
}
</style>